package com.ruoyi.common.utils.jm.ofd;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.UUID;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERUTF8String;

public class GBSeal {

	public static byte[] GetBCSm2SignVal(byte[] bSignVal64) throws IOException{
		ASN1EncodableVector vSignVal = new ASN1EncodableVector();
		byte[] b1 = new byte[32];
		byte[] b2 = new byte[32];
		System.arraycopy(bSignVal64, 0, b1, 0, 32);
		System.arraycopy(bSignVal64, 32, b2, 0, 32);
		BigInteger big1 = toBigInteger(b1);
		BigInteger big2 = toBigInteger(b2);
		vSignVal.add(new ASN1Integer(big1));
		vSignVal.add(new ASN1Integer(big2));
		DERSequence derSignVal = new DERSequence(vSignVal);
		byte[] bSignVal = derSignVal.getEncoded();
		return bSignVal;
	}

	private static  BigInteger toBigInteger(byte[] v)
	{
		BigInteger bigInt = new BigInteger(1,v);
		return bigInt;
	}

	private static ASN1EncodableVector CreateHeader()
	{
		ASN1EncodableVector v = new ASN1EncodableVector();
		v.add(new DERIA5String("ES"));
		v.add(new ASN1Integer(4));
		v.add(new DERIA5String("BJCLTTEST"));
		return v;
	}

	private static ASN1EncodableVector CreatePropertyInfo(int sealType,String sealName,byte[] bSignerCert,String makeDate,String validateBeginDate,String validateEndDate)
	{
		ASN1EncodableVector v = new ASN1EncodableVector();
		v.add(new ASN1Integer(sealType));		//印章类型
		v.add(new DERUTF8String(sealName));		//印章名称
		v.add(new ASN1Integer(1));				//表示下面是证书列表，而不是证书hash
		ASN1EncodableVector vCert = new ASN1EncodableVector();
		vCert.add(new DEROctetString(bSignerCert));	//印章绑定的数字证书
		v.add(new DERSequence(vCert));
		v.add(new DERGeneralizedTime(makeDate));
		v.add(new DERGeneralizedTime(validateBeginDate));
		v.add(new DERGeneralizedTime(validateEndDate));
		return v;
	}

	private static ASN1EncodableVector CreatePictureInfo(String sType,byte[] bPicData,int iWidth,int iHeight)
	{
		ASN1EncodableVector v = new ASN1EncodableVector();
		DERIA5String ia5String = new DERIA5String(sType);		//图像类型(GIF BMP JPG ....)
		DEROctetString octString = new DEROctetString(bPicData);	//图像数据
		v.add(ia5String);
		v.add(octString);
		v.add(new ASN1Integer(iWidth));
		v.add(new ASN1Integer(iHeight));

		return v;

	}

	/***
	 *@author lijin
	 *@param sealID 	印章ID
	 *@param iVersion	印章版本，固定填写  2
	 *@param cltID		诚利通公司ID
	 *@param iSealType	印章类型，1：公章 2：签名
	 *@param sealName	印章名称
	 *@param bSignerCert 印章绑定的数字证书
	 *@param makeDate   印章制作日期 ，格式为 200324124526Z, 表示2020年3月24日12时45分26秒,以字母Z结尾
	 *@param beginDate  有效期起始日
	 *@param endDate    有效期截止日
	 *@param sPicType   印章图像类型： GIF、BMP、PNG、JPG
	 *@param bPicData   印章图像
	 *@param iPicWidth  印章宽度（毫米）
	 *@param iPicHeight 印章高度
	 *@param bMakerCert 电子印章平台证书
	 *@param sAlgOid    签名算法，固定为 "1.2.156.10197.1.501"
	 *@param pbMakerPfx 印章平台的SM2根PFX
	 *@param sMakerPfxPin SM2根PFX的密码
	 */
	public static byte[] CreateGBSeal(
				String 		sealID,
				int 		iVersion,
				String		cltID,
				int			iSealType,
				String		sealName,
				byte[]		bSignerCert,
				String		makeDate,
				String		beginDate,
				String		endDate,
				String		sPicType,
				byte[]		bPicData,
				int			iPicWidth,
				int			iPicHeight,
				byte[]		bMakerCert,
				String 		sAlgOid,
				byte[]		bMakerPfx,
				String		sPfxPin
			)
	{
		try
		{
			ASN1EncodableVector Header = CreateHeader();
			ASN1EncodableVector PictureInfo = CreatePictureInfo(sPicType,bPicData,iPicWidth,iPicHeight);
			ASN1EncodableVector PropertyInfo = CreatePropertyInfo(iSealType,sealName,bSignerCert,makeDate,beginDate,endDate);

			ASN1EncodableVector sealInfo = new ASN1EncodableVector();
			sealInfo.add(new DERSequence(Header));
			sealInfo.add(new DERIA5String(sealID));
			sealInfo.add(new DERSequence(PropertyInfo));
			sealInfo.add(new DERSequence(PictureInfo));

			ASN1EncodableVector seal = new ASN1EncodableVector();
			seal.add(new DERSequence(sealInfo));				//印章信息

			//对信息域进行签名
			DERSequence der = new DERSequence(sealInfo);
			byte[] bForSign = der.getEncoded();
			byte[] bSignVal = SM2Crypto.SignDateForSeal(bMakerCert, bForSign, bMakerPfx, sPfxPin);

			//组装最终的印章信息
			seal.add(new DEROctetString(bMakerCert));			//制章人证书
			seal.add(new ASN1ObjectIdentifier(sAlgOid));	//签名算法标识

			//签名值
			ASN1EncodableVector vSignVal = new ASN1EncodableVector();
			byte[] b1 = new byte[32];
			byte[] b2 = new byte[32];
			System.arraycopy(bSignVal, 0, b1, 0, 32);
			System.arraycopy(bSignVal, 32, b2, 0, 32);
			BigInteger big1 = toBigInteger(b1);
			BigInteger big2 = toBigInteger(b2);
			vSignVal.add(new ASN1Integer(big1));
			vSignVal.add(new ASN1Integer(big2));
			DERSequence derSignVal = new DERSequence(vSignVal);
			bSignVal = derSignVal.getEncoded();

			seal.add(new DERBitString(bSignVal));			//签名值

			der = new DERSequence(seal);
			return der.getEncoded();

		}catch(IOException e)
		{
			e.printStackTrace();
			return null;
		}
	}



	public static byte[] CreateGBSeal(
			String 		sealID,
			int 		iVersion,
			String		cltID,
			int			iSealType,
			String		sealName,
			byte[]		bSignerCert,
			String		makeDate,
			String		beginDate,
			String		endDate,
			String		sPicType,
			byte[]		bPicData,
			int			iPicWidth,
			int			iPicHeight,
			byte[]		bMakerCert,
			String 		sAlgOid,
			String		sPublicKey,
			String		sPrivateKey
		)
{
	try
	{
		ASN1EncodableVector Header = CreateHeader();
		ASN1EncodableVector PictureInfo = CreatePictureInfo(sPicType,bPicData,iPicWidth,iPicHeight);
		ASN1EncodableVector PropertyInfo = CreatePropertyInfo(iSealType,sealName,bSignerCert,makeDate,beginDate,endDate);

		ASN1EncodableVector sealInfo = new ASN1EncodableVector();
		sealInfo.add(new DERSequence(Header));
		sealInfo.add(new DERIA5String(sealID));
		sealInfo.add(new DERSequence(PropertyInfo));
		sealInfo.add(new DERSequence(PictureInfo));

		ASN1EncodableVector seal = new ASN1EncodableVector();
		seal.add(new DERSequence(sealInfo));				//印章信息

		//对信息域进行签名
		DERSequence der = new DERSequence(sealInfo);
		byte[] bForSign = der.getEncoded();
		byte[] bSignVal = SM2Crypto.SignDateForSeal(bMakerCert, bForSign,sPublicKey,sPrivateKey);

		//组装最终的印章信息
		seal.add(new DEROctetString(bMakerCert));			//制章人证书
		seal.add(new ASN1ObjectIdentifier(sAlgOid));	//签名算法标识

		//签名值
		ASN1EncodableVector vSignVal = new ASN1EncodableVector();
		byte[] b1 = new byte[32];
		byte[] b2 = new byte[32];
		System.arraycopy(bSignVal, 0, b1, 0, 32);
		System.arraycopy(bSignVal, 32, b2, 0, 32);
		BigInteger big1 = toBigInteger(b1);
		BigInteger big2 = toBigInteger(b2);
		vSignVal.add(new ASN1Integer(big1));
		vSignVal.add(new ASN1Integer(big2));
		DERSequence derSignVal = new DERSequence(vSignVal);
		bSignVal = derSignVal.getEncoded();

		seal.add(new DERBitString(bSignVal));			//签名值

		der = new DERSequence(seal);
		return der.getEncoded();

	}catch(IOException e)
	{
		e.printStackTrace();
		return null;
	}
}

	/***
	 *
	 * @param bSeal 	印章数据
	 * @param bSignTime	签章时间
	 * @param bDocHash	原文杂凑
	 * @param bDocPorperty 原文属性
	 */
	public static byte[] CreateTbs(byte[] bSeal,String sSignTime,byte[] bDocHash,String sDocProperty)
	{
		ASN1EncodableVector v = new ASN1EncodableVector();
		//版本，固定V4
		v.add(new ASN1Integer(4));
		//电子印章
		try {
			ASN1Sequence seal = (ASN1Sequence)ASN1Sequence.fromByteArray(bSeal);
			v.add(seal);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		//签章时间
		v.add(new DERGeneralizedTime(sSignTime));
		//原文杂凑
		v.add(new DERBitString(bDocHash));
		//原文属性
		v.add(new DERIA5String(sDocProperty));

		DERSequence der = new DERSequence(v);
		try {
			return der.getEncoded();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static ASN1EncodableVector CreateTbsEx(byte[] bSeal,String sSignTime,byte[] bDocHash,String sDocProperty)
	{
		ASN1EncodableVector v = new ASN1EncodableVector();
		//版本，固定V4
		v.add(new ASN1Integer(4));
		//电子印章
		try {
			ASN1Sequence seal = (ASN1Sequence)ASN1Sequence.fromByteArray(bSeal);
			v.add(seal);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		//签章时间
		v.add(new DERGeneralizedTime(sSignTime));
		//原文杂凑
		v.add(new DERBitString(bDocHash));
		//原文属性
		v.add(new DERIA5String(sDocProperty));

		return v;
	}

//	private static byte[] CreateTbsForSign(byte[] bSeal,String sSignTime,byte[] bDocHash,String sDocProperty,byte[] bSignCert,String sAlgOid)
//	{
//		ASN1EncodableVector v = new ASN1EncodableVector();
//
//		//TBS
//		ASN1EncodableVector tbs = CreateTbs(bSeal,sSignTime,bDocHash,sDocProperty);
//		v.add(new DERSequence(tbs));
//		//签章人证书
//		v.add(new DEROctetString(bSignCert));
//		//算法
//		v.add(new ASN1ObjectIdentifier(sAlgOid));
//
//		DERSequence der = new DERSequence(v);
//		try {
//			return der.getEncoded();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//			return null;
//		}
//	}

	public static byte[] CreateSignStruct(byte[] bSeal,String sSignTime,byte[] bDocHash,String sDocProperty,byte[] bSignCert,String sAlgOid,byte[] bSignVal)
	{
		try {
			ASN1EncodableVector v = new ASN1EncodableVector();
			ASN1EncodableVector tbs = CreateTbsEx(bSeal,sSignTime,bDocHash,sDocProperty);
			v.add(new DERSequence(tbs));
			//签章人证书
			v.add(new DEROctetString(bSignCert));
			//算法
			v.add(new ASN1ObjectIdentifier(sAlgOid));
			//签名值
			ASN1EncodableVector vSignVal = new ASN1EncodableVector();
			byte[] b1 = new byte[32];
			byte[] b2 = new byte[32];
			System.arraycopy(bSignVal, 0, b1, 0, 32);
			System.arraycopy(bSignVal, 32, b2, 0, 32);
			BigInteger big1 = toBigInteger(b1);
			BigInteger big2 = toBigInteger(b2);
			vSignVal.add(new ASN1Integer(big1));
			vSignVal.add(new ASN1Integer(big2));
			DERSequence derSignVal = new DERSequence(vSignVal);
			bSignVal = derSignVal.getEncoded();

			v.add(new DERBitString(bSignVal));
			DERSequence der = new DERSequence(v);
			try {
				return der.getEncoded();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}


		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

	}
	/*
	 * 此函数生成符合国办要求的签名值
	 * */

	public static byte[] SignIt(byte[] bSeal,String sSignTime,byte[] bDocHash,String sDocProperty,byte[] bSignCert,String sAlgOid,String sPub,String sPrv) throws IOException
	{
		byte[] bForSign = CreateTbs(bSeal,sSignTime,bDocHash,sDocProperty);

		if(bForSign == null)
			return null;
		try {
			byte[] bSignVal = SM2Crypto.SignDateForSeal(bSignCert, bForSign, sPub, sPrv);
			ASN1EncodableVector v = new ASN1EncodableVector();

			ASN1EncodableVector tbs = CreateTbsEx(bSeal,sSignTime,bDocHash,sDocProperty);
			v.add(new DERSequence(tbs));
			//签章人证书
			v.add(new DEROctetString(bSignCert));
			//算法
			v.add(new ASN1ObjectIdentifier(sAlgOid));
			//签名值
			ASN1EncodableVector vSignVal = new ASN1EncodableVector();
			byte[] b1 = new byte[32];
			byte[] b2 = new byte[32];
			System.arraycopy(bSignVal, 0, b1, 0, 32);
			System.arraycopy(bSignVal, 32, b2, 0, 32);
			BigInteger big1 = toBigInteger(b1);
			BigInteger big2 = toBigInteger(b2);
			vSignVal.add(new ASN1Integer(big1));
			vSignVal.add(new ASN1Integer(big2));
			DERSequence derSignVal = new DERSequence(vSignVal);
			bSignVal = derSignVal.getEncoded();

			v.add(new DERBitString(bSignVal));
			DERSequence der = new DERSequence(v);
			try {
				return der.getEncoded();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}


		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static void main(String[] args) throws IOException {

		// 以下代码制作一个国办格式的印章
		//用户证书
//		File f = new File("D:/电子发票OESV4库/sealinfo/sm2user.cer");
		File f = new File("D:/gbcert.cer");
		FileInputStream fis = new FileInputStream(f);
		int iLen = (int)f.length();
		byte[] bUserCert = new byte[iLen];
		fis.read(bUserCert);
		fis.close();

		//颁发者证书
		f = new File("D:/SM2Certs/sm2root.cer");
		fis = new FileInputStream(f);
		iLen = (int)f.length();
		byte[] bRootCert = new byte[iLen];
		fis.read(bRootCert);
		fis.close();

		//颁发者PFX
		f = new File("D:/SM2Certs/sm2root.pfx");
		fis = new FileInputStream(f);
		iLen = (int)f.length();
		byte[] bRootPfx = new byte[iLen];
		fis.read(bRootPfx);
		fis.close();

		//印章图
//		f = new File("D:/电子发票OESV4库/sealinfo/seal.ofd");
		f = new File("D:/12.gif");
		fis = new FileInputStream(f);
		iLen = (int)f.length();
		byte[] bGif = new byte[iLen];
		fis.read(bGif);
		fis.close();

		String uuid = UUID.randomUUID().toString();

		String sPsw = "e03f2034";

	//	byte[] bAsn1Seal = GBSeal.CreateGBSeal(uuid, 2, "BJCLTDZYZPT", 3, "国办标准测试章", bUserCert, "20200324102030Z", "20200324102030Z", "20220324102030Z", "ofd", bGif, 30, 20, bRootCert, "1.2.156.10197.1.501", bRootPfx, sPsw);
		byte[] bAsn1Seal = GBSeal.CreateGBSeal(uuid, 2, "BJCLTDZYZPT", 3, "国办标准测试章", bUserCert, "20200324102030Z", "20200324102030Z", "20220324102030Z", "png", bGif, 40, 40, bRootCert, "1.2.156.10197.1.501", bRootPfx, sPsw);
		if(bAsn1Seal != null)
		{
	//		f = new File("D:/电子发票OESV4库/sealinfo/gbseal.dat");
			f = new File("D:/gbsealtest.dat");
			FileOutputStream fos = new FileOutputStream(f);
			fos.write(bAsn1Seal);
			fos.close();
	//		System.out.println("D:/电子发票OESV4库/sealinfo/gbseal.dat");
		}else
			System.out.println("error.................");

	}

}
